from asyncio import subprocess
import random
import requests
import json
import csv
import time
import logging
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import urllib.parse
import os

# 设置日志
logging.basicConfig(
    filename="zhongyaocaixiangxi.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

# 配置请求头
headers = {
    "Accept": "application/json, text/plain, */*",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Connection": "keep-alive",
    "Content-Type": "application/json;charset=UTF-8",
    "DNT": "1",
    "Host": "www.tcmip.cn:18124",
    "Origin": "http://www.tcmip.cn",
    "Referer": "http://www.tcmip.cn/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
}

# 设置请求重试策略
retry_strategy = Retry(
    total=5,
    backoff_factor=1,
    status_forcelist=[500, 502, 503, 504],
)

adapter = HTTPAdapter(max_retries=retry_strategy)

# 创建请求会话
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)

# 目标 CSV 文件
csv_filename = "zhongyaocaixiangxi.csv"

# 初始化 CSV（如果文件不存在，添加表头）
if not os.path.exists(csv_filename):
    with open(csv_filename, mode="w", encoding="utf-8", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(
            [
                "药材名",
                "药材拉丁名",
                "药材英文名",
                "科",
                "产地",
                "采集时间",
                "药用部位",
                "中药材类别（按功效划分）",
                "性",
                "味",
                "归经",
                "功效",
                "性状",
                "规格",
                "数据库交叉检索",
                "成分",
                "上限",
                "下限",
                "单位",
                "相似中药材名",
                "相似中药材值",
                "相似基因名",
                "相似基因值"
            ]
        )


# 获取 API 数据
def get_data(interface_url: str):
    try:
        response = session.get(interface_url, headers=headers, timeout=10)
        response.raise_for_status()  # 遇到 HTTP 错误状态码则抛出异常
        return response.json().get("data", [])
    except Exception as e:
        logging.error(f"请求失败: {e}")
        return []

time_g_begin = time.time()

# 读取药材列表
with open("zhongyaocai.csv", mode="r", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        time_begin = time.time()

        name = row[0]
        url = f"http://www.tcmip.cn:18124/home/detail/?id={urllib.parse.quote(name)}&type=herb&language=cn"

        # 获取数据
        data = get_data(url)

        # 解析基本信息
        herb_info = {
            "药材名": name,
            "药材拉丁名": "",
            "药材英文名": "",
            "科": "",
            "产地": "",
            "采集时间": "",
            "药用部位": "",
            "中药材类别（按功效划分）": "",
            "性": "",
            "味": "",
            "归经": "",
            "功效": "",
            "性状": "",
            "规格": "",
            "数据库交叉检索": "",
        }
        component = {
            "component": "",
            "up": 0,
            "down": 0,
            "unit": "",
        }

        similar_chenmistary = {
            "name": "",
            "value": "",
        }
        similar_gene = {
            "name": "",
            "value": "",
        }

        chinese_patent_drugs = []  # 存放相关中成药数据

        for section in data:
            if section["key"] == "基本信息":
                for item in section["value"]:
                    if item["key"] in herb_info:
                        if item["key"] == "数据库交叉检索":
                            herb_info[item["key"]] = ",".join(item["value"])
                        else:
                            herb_info[item["key"]] = item["value"]
            elif section["key"] == "指标性成分的定量信息":
                for key, value in section["value"][0].items():
                    component[key] = value

            elif section["key"] == "相似中药材":
                chenmistary = section["value"][0]
                name: str = ""
                value: str = ""
                for sublist in chenmistary["value"]:
                    name += sublist[0]["value"] + ","
                    value += sublist[1]["value"] + ","

                if len(section["value"]) > 1:
                    gene = section["value"][1]
                    name_gene: str = ""
                    value_gene: str = ""
                    for sublist in gene["value"]:
                        name_gene += sublist[0]["value"] + ","
                        value_gene += sublist[1]["value"] + ","

                    name = name[:-1]
                    value = value[:-1]
                    name_gene = name_gene[:-1]
                    value_gene = value_gene[:-1]
                    similar_chenmistary["name"] = name
                    similar_chenmistary["value"] = value
                    similar_gene["name"] = name_gene
                    similar_gene["value"] = value_gene

        # 将提取的数据写入到 CSV 文件中
        with open(csv_filename, mode="a", encoding="utf-8", newline="") as f:
            writer = csv.writer(f)
            writer.writerow([
                herb_info["药材名"],
                herb_info["药材拉丁名"],
                herb_info["药材英文名"],
                herb_info["科"],
                herb_info["产地"],
                herb_info["采集时间"],
                herb_info["药用部位"],
                herb_info["中药材类别（按功效划分）"],
                herb_info["性"],
                herb_info["味"],
                herb_info["归经"],
                herb_info["功效"],
                herb_info["性状"],
                herb_info["规格"],
                herb_info["数据库交叉检索"],
                component["component"],
                component["up"],
                component["down"],
                component["unit"],
                similar_chenmistary["name"],
                similar_chenmistary["value"],
                similar_gene["name"],
                similar_gene["value"]
            ])

        logging.info(f"已写入: {row[0]}")
        logging.info(f"耗时: {round(time.time() - time_begin):.2f}")
        time.sleep(random.uniform(10, 15))  # 避免触发反爬机制

logging.info("所有数据请求完成！")
try:
    subprocess.run(["pm2", "stop", "1"], check=True)
    logging.info(f"总耗时: {round((time.time()-time_g_begin)/60,3)} min")
    logging.info("pm2 进程 1 已停止。")
except subprocess.CalledProcessError as e:
    logging.error(f"停止 pm2 进程时出错：{e}")
